/**
@author		Jong Min, Lee
@date		  02/09/2014
@brief		delegate template

copyright(c) Tae Young Soft. All right reserved. 2014
*/
#pragma once

template<class TSender>
class TBaseDelegate
{
public:

  virtual BOOL equal(const TBaseDelegate<TSender>* other) = 0;

  virtual void operator()(const TSender* sender,
                          void* parameter) = 0;

  virtual void call(const TSender* sender,
                    void* parameter) = 0;
};

template<class TReceiver, class TSender>
class TDelegate : public TBaseDelegate<TSender>
{
private:
  typedef void (TReceiver::*PTF)(const TSender*, void*);

  PTF m_theFunc;

  TReceiver* m_theObject;

public:

  TDelegate()
    : m_theFunc(nullptr)
    , m_theObject(nullptr)
  {}

  TDelegate(TReceiver* object, PTF func)
    : m_theObject(object)
    , m_theFunc(func)
  {}

  void set(TReceiver* object, PTF func)
  {
    m_theObject = object;
    m_theFunc = func;
  }

  virtual BOOL equal(const TBaseDelegate<TSender>* other)
  {
    const TDelegate<TReceiver, TSender>* theOther;
    theOther = static_cast<const TDelegate<TReceiver, TSender>*>(other);
    
    ASSERT(theOther != NULL);
    ASSERT(m_theObject != NULL);

    return(theOther->m_theObject == m_theObject &&
           theOther->m_theFunc == m_theFunc);
  }

  virtual void operator()(const TSender* sender, void* parameter)
  {
    if(sender != nullptr)
    {
      if(m_theObject != nullptr && m_theFunc != nullptr)
        (m_theObject->*m_theFunc)(sender, parameter);
    }
  }

  virtual void call(const TSender* sender, void* parameter)
  {
    if(sender != nullptr)
    {
      if(m_theObject != nullptr && m_theFunc != nullptr)
        (m_theObject->*m_theFunc)(sender, parameter);
    }
  }
};

